#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#define ACPI_EVAL_INPUT_BUFFER_SIGNATURE                    'BieA'
#define ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE     'IieA'
#define ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING_SIGNATURE      'SieA'
#define ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE            'CieA'
#define ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE                   'BoeA'
#if (NTDDI_VERSION >= NTDDI_VISTA)
#define ACPI_EVAL_INPUT_BUFFER_SIGNATURE_EX                 'AieA'
#define ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE_EX  'DieA'
#define ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING_SIGNATURE_EX   'EieA'
#define ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE_EX         'FieA'
#define ACPI_ENUM_CHILDREN_OUTPUT_BUFFER_SIGNATURE          'GieA'
#define ACPI_ENUM_CHILDREN_INPUT_BUFFER_SIGNATURE           'HieA'
#endif

#define ACPI_METHOD_ARGUMENT_INTEGER                      0x0
#define ACPI_METHOD_ARGUMENT_STRING                       0x1
#define ACPI_METHOD_ARGUMENT_BUFFER                       0x2
#define ACPI_METHOD_ARGUMENT_PACKAGE                      0x3
#define ACPI_METHOD_ARGUMENT_PACKAGE_EX                   0x4

#define ACPI_ACQUIRE_GLOBAL_LOCK_SIGNATURE              'LgaA'
#define ACPI_RELEASE_GLOBAL_LOCK_SIGNATURE              'LgrA'

#define ACPI_OBJECT_HAS_CHILDREN            0x1

#define ENUM_CHILDREN_IMMEDIATE_ONLY        0x1
#define ENUM_CHILDREN_MULTILEVEL            0x2
#define ENUM_CHILDREN_NAME_IS_FILTER        0x4

typedef struct _ACPI_EVAL_INPUT_BUFFER {
  ULONG Signature;
  _ANONYMOUS_UNION union {
    UCHAR MethodName[4];
    ULONG MethodNameAsUlong;
  } DUMMYUNIONNAME;
} ACPI_EVAL_INPUT_BUFFER, *PACPI_EVAL_INPUT_BUFFER;

typedef struct _ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER {
  ULONG Signature;
  _ANONYMOUS_UNION union {
    UCHAR MethodName[4];
    ULONG MethodNameAsUlong;
  } DUMMYUNIONNAME;
  ULONG IntegerArgument;
} ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER, *PACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER;

typedef struct _ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING {
  ULONG Signature;
  _ANONYMOUS_UNION union {
    UCHAR MethodName[4];
    ULONG MethodNameAsUlong;
  } DUMMYUNIONNAME;
  ULONG StringLength;
  _Field_size_bytes_(StringLength) _Null_terminated_ UCHAR String[ANYSIZE_ARRAY];
} ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING, *PACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING;

typedef struct _ACPI_METHOD_ARGUMENT {
  USHORT Type;
  USHORT DataLength;
  _ANONYMOUS_UNION union {
    ULONG Argument;
    _Field_size_bytes_(DataLength) UCHAR Data[ANYSIZE_ARRAY];
  } DUMMYUNIONNAME;
} ACPI_METHOD_ARGUMENT;
typedef ACPI_METHOD_ARGUMENT UNALIGNED *PACPI_METHOD_ARGUMENT;

typedef struct _ACPI_EVAL_INPUT_BUFFER_COMPLEX {
  ULONG Signature;
  _ANONYMOUS_UNION union {
    UCHAR MethodName[4];
    ULONG MethodNameAsUlong;
  } DUMMYUNIONNAME;
  ULONG Size;
  ULONG ArgumentCount;
  ACPI_METHOD_ARGUMENT Argument[ANYSIZE_ARRAY];
} ACPI_EVAL_INPUT_BUFFER_COMPLEX, *PACPI_EVAL_INPUT_BUFFER_COMPLEX;

typedef struct _ACPI_EVAL_OUTPUT_BUFFER {
  ULONG Signature;
  ULONG Length;
  ULONG Count;
  _Field_size_bytes_(Length) ACPI_METHOD_ARGUMENT Argument[ANYSIZE_ARRAY];
} ACPI_EVAL_OUTPUT_BUFFER;
typedef ACPI_EVAL_OUTPUT_BUFFER UNALIGNED *PACPI_EVAL_OUTPUT_BUFFER;

typedef struct _ACPI_MANIPULATE_GLOBAL_LOCK_BUFFER {
  ULONG Signature;
  PVOID LockObject;
} ACPI_MANIPULATE_GLOBAL_LOCK_BUFFER, *PACPI_MANIPULATE_GLOBAL_LOCK_BUFFER;

typedef struct _ACPI_EVAL_INPUT_BUFFER_EX {
  ULONG Signature;
  _Null_terminated_ CHAR MethodName[256];
} ACPI_EVAL_INPUT_BUFFER_EX, *PACPI_EVAL_INPUT_BUFFER_EX;

typedef struct _ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_EX {
  ULONG Signature;
  _Null_terminated_ CHAR MethodName[256];
  ULONG64 IntegerArgument;
} ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_EX, *PACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_EX;

typedef struct _ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING_EX {
  ULONG Signature;
  CHAR MethodName[256];
  ULONG StringLength;
  _Field_size_(StringLength) _Null_terminated_ UCHAR String[ANYSIZE_ARRAY];
} ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING_EX, *PACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING_EX;

typedef struct _ACPI_EVAL_INPUT_BUFFER_COMPLEX_EX {
  ULONG Signature;
  CHAR MethodName[256];
  ULONG Size;
  ULONG ArgumentCount;
  _Field_size_(ArgumentCount) ACPI_METHOD_ARGUMENT Argument[ANYSIZE_ARRAY];
} ACPI_EVAL_INPUT_BUFFER_COMPLEX_EX, *PACPI_EVAL_INPUT_BUFFER_COMPLEX_EX;

typedef struct _ACPI_ENUM_CHILDREN_INPUT_BUFFER {
  ULONG Signature;
  ULONG Flags;
  ULONG NameLength;
  _Field_size_bytes_(NameLength) _Null_terminated_ CHAR Name[ANYSIZE_ARRAY];
} ACPI_ENUM_CHILDREN_INPUT_BUFFER, *PACPI_ENUM_CHILDREN_INPUT_BUFFER;

typedef struct _ACPI_ENUM_CHILD {
  ULONG Flags;
  ULONG NameLength;
  _Field_size_bytes_(NameLength) _Null_terminated_ CHAR Name[ANYSIZE_ARRAY];
} ACPI_ENUM_CHILD;
typedef ACPI_ENUM_CHILD UNALIGNED *PACPI_ENUM_CHILD;

typedef struct _ACPI_ENUM_CHILDREN_OUTPUT_BUFFER {
  ULONG Signature;
  ULONG NumberOfChildren;
  ACPI_ENUM_CHILD Children[ANYSIZE_ARRAY];
} ACPI_ENUM_CHILDREN_OUTPUT_BUFFER; 
typedef ACPI_ENUM_CHILDREN_OUTPUT_BUFFER UNALIGNED *PACPI_ENUM_CHILDREN_OUTPUT_BUFFER;

#define ACPI_METHOD_ARGUMENT_LENGTH( DataLength )                           \
  (FIELD_OFFSET(ACPI_METHOD_ARGUMENT, Data) + max(sizeof(ULONG), DataLength))

#define ACPI_METHOD_ARGUMENT_LENGTH_FROM_ARGUMENT( Argument )               \
  (ACPI_METHOD_ARGUMENT_LENGTH(((PACPI_METHOD_ARGUMENT)Argument)->DataLength))

#define ACPI_METHOD_NEXT_ARGUMENT( Argument )                               \
  (PACPI_METHOD_ARGUMENT) ( (PUCHAR) Argument +                             \
  ACPI_METHOD_ARGUMENT_LENGTH_FROM_ARGUMENT( Argument ) )


#define ACPI_METHOD_SET_ARGUMENT_INTEGER( MethodArgument, IntData )         \
  { MethodArgument->Type = ACPI_METHOD_ARGUMENT_INTEGER;                    \
    MethodArgument->DataLength = sizeof(ULONG);                             \
    MethodArgument->Argument = IntData; }

#define ACPI_METHOD_SET_ARGUMENT_STRING( Argument, StrData )                \
  { Argument->Type = ACPI_METHOD_ARGUMENT_STRING;                           \
    Argument->DataLength = strlen((PCHAR)StrData) + sizeof(UCHAR);          \
    RtlCopyMemory(&Argument->Data[0],(PUCHAR)StrData,Argument->DataLength); }

#define ACPI_METHOD_SET_ARGUMENT_BUFFER( Argument, BuffData, BuffLength )   \
  { Argument->Type = ACPI_METHOD_ARGUMENT_BUFFER;                           \
    Argument->DataLength = BuffLength;                                      \
    RtlCopyMemory(&Argument->Data[0],(PUCHAR)BuffData,Argument->DataLength); }

#define ACPI_ENUM_CHILD_LENGTH_FROM_CHILD( Child ) \
  ( (2* sizeof (ULONG)) + Child->NameLength )

#define ACPI_ENUM_CHILD_NEXT( Child )           \
  (PACPI_ENUM_CHILD) ( (PUCHAR) Child +         \
  ACPI_ENUM_CHILD_LENGTH_FROM_CHILD( Child ) )

#define IOCTL_ACPI_ASYNC_EVAL_METHOD    CTL_CODE(FILE_DEVICE_ACPI, 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_ACPI_EVAL_METHOD          CTL_CODE(FILE_DEVICE_ACPI, 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_ACPI_ACQUIRE_GLOBAL_LOCK  CTL_CODE(FILE_DEVICE_ACPI, 4, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_ACPI_RELEASE_GLOBAL_LOCK  CTL_CODE(FILE_DEVICE_ACPI, 5, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#if (NTDDI_VERSION >= NTDDI_VISTA)
#define IOCTL_ACPI_EVAL_METHOD_EX       CTL_CODE(FILE_DEVICE_ACPI, 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_ACPI_ASYNC_EVAL_METHOD_EX CTL_CODE(FILE_DEVICE_ACPI, 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_ACPI_ENUM_CHILDREN        CTL_CODE(FILE_DEVICE_ACPI, 8, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#endif

#ifdef __cplusplus
}
#endif
